using System;
using System.IO;
using FireStarter.CodeGeneration;
using FireStarterModeller.BO;
using NUnit.Framework;

namespace FireStarter.Test.CodeGeneration
{
    [TestFixture]
    public class TestVWGProjectGenerator : TestProjectGeneratorBase
    {

        private static VWGProjectGenerator CreateVWGProjectReadyToGenerate()
        {
            VWGProjectGenerator projectGenerator = new VWGProjectGenerator();
            CreateSolutionGenerator(projectGenerator);
            projectGenerator.ProjectPath = GetRootedPath(Path.Combine(TEST_PROJECTS_FOLDER, GetRandomString()));
            projectGenerator.ProjectName = "TestProject.VWG";
            projectGenerator.ModelSolution.BOProjectName = GetRandomString();
            projectGenerator.ModelSolution.UIProjectName = GetRandomString();
            projectGenerator.ModelSolution.UIVWGProjectName = GetRandomString();
            return projectGenerator;
        }

        protected override IProjectGenerator CreateProjectReadyToGenerate()
        {
            return CreateVWGProjectReadyToGenerate();
        }

        protected override IProjectGenerator CreateProjectGenerator()
        {
            return new VWGProjectGenerator();
        }

        private void AssertProjectGeneratedCorrectly(VWGProjectGenerator vwgProjectGenerator, ProjectFileManager uiProjectFileManager)
        {
            string libFolderName = vwgProjectGenerator.SolutionGenerator.HabaneroReferencePath;
            libFolderName = Utilities.GetRelativePath(libFolderName, vwgProjectGenerator.ProjectPath);
            string projectFileName = vwgProjectGenerator.ProjectFileName;
            Assert.IsTrue(Directory.Exists(vwgProjectGenerator.ProjectPath));
            Assert.IsTrue(File.Exists(projectFileName));
            string projectFileContents = File.ReadAllText(projectFileName);
            StringAssert.Contains("<Compile Include=\"Global.asax.cs\">", projectFileContents);
            StringAssert.Contains("<DependentUpon>Global.asax</DependentUpon>", projectFileContents);
            StringAssert.Contains("<Compile Include=\"MainForm.cs\" />", projectFileContents);
            StringAssert.Contains("<None Include=\"Web.config\" />", projectFileContents);
            StringAssert.Contains("<Compile Include=\"UIManagerVWG.cs\" />", projectFileContents);
            StringAssert.Contains(@"<Compile Include=""Properties\AssemblyInfo.cs"" />", projectFileContents);
            AssertHasProjectReference(projectFileContents, vwgProjectGenerator, uiProjectFileManager);
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.Base.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.BO.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.Faces.Base.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Habanero.Faces.VWG.dll", libFolderName));
            AssertHasNotReference(projectFileContents, string.Format(@"{0}\Habanero.Util.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\log4net.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Gizmox.WebGUI.Forms.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Gizmox.WebGUI.Common.dll", libFolderName));
            AssertHasReference(projectFileContents, string.Format(@"{0}\Gizmox.WebGUI.Server.dll", libFolderName));
            AssertHasSystemReference(projectFileContents, string.Format(@"System.Web"));
        }

        [Test]
        public void TestCreateVWGProjectGenerator()
        {
            //---------------Set up test pack-------------------

            //---------------Assert Precondition----------------

            //---------------Execute Test ----------------------
            IProjectGenerator vwgProjectGenerator = CreateProjectGenerator();
            //---------------Test Result -----------------------
            Assert.IsNotNull(vwgProjectGenerator);
            Assert.IsInstanceOf(typeof (VWGProjectGenerator), vwgProjectGenerator);
        }

        //[Test]
        //public void TestUIProjectReference()
        //{
        //    //---------------Set up test pack-------------------
        //    string uiProjectName = GetRandomString();
        //    VWGProjectGenerator vwgProjectGenerator = new VWGProjectGenerator();
        //    //---------------Assert Precondition----------------
        //    Assert.IsNull(vwgProjectGenerator.UIProjectFileName);
        //    //---------------Execute Test ----------------------
        //    vwgProjectGenerator.UIProjectFileName = uiProjectName;
        //    //---------------Test Result -----------------------
        //    Assert.AreEqual(uiProjectName, vwgProjectGenerator.UIProjectFileName);
        //}

        //[Test]
        //public void TestGenerate_Fails_UiProjectReferenceNotSet()
        //{
        //    //---------------Set up test pack-------------------
        //    VWGProjectGenerator vwgProjectGenerator = CreateVWGProjectReadyToGenerate();
        //    vwgProjectGenerator.UIProjectFileName = null;
        //    //---------------Assert Precondition----------------
        //    Assert.IsNull(vwgProjectGenerator.UIProjectFileName);
        //    //---------------Execute Test ----------------------
        //    Exception exception = null;
        //    try
        //    {
        //        vwgProjectGenerator.Generate();
        //    }
        //    catch (Exception ex)
        //    {
        //        exception = ex;
        //    }
        //    //---------------Test Result -----------------------
        //    Assert.IsNotNull(exception, "Exception Expected");
        //    Assert.IsInstanceOf(typeof(ReferenceMissingException), exception);
        //    ReferenceMissingException referenceMissingException = (ReferenceMissingException)exception;
        //    Assert.AreEqual("UI Project", referenceMissingException.ReferenceName);
        //}

        [Test]
        public void TestGenerate_Creates_ProjectFile_IfDoesNotExist()
        {
            //---------------Set up test pack-------------------
            VWGProjectGenerator vwgProjectGenerator = CreateVWGProjectReadyToGenerate();
            ProjectFileManager uiProjectFileManager = CreateRandomProjectFile(vwgProjectGenerator.ModelSolution.UIProjectName);
            string projectFileName = vwgProjectGenerator.ProjectFileName;
            //---------------Assert Precondition----------------
            Assert.IsFalse(File.Exists(projectFileName));
            //---------------Execute Test ----------------------
            vwgProjectGenerator.Generate();
            //---------------Test Result -----------------------
            AssertProjectGeneratedCorrectly(vwgProjectGenerator, uiProjectFileManager);
        }

        public abstract class TestVWGProjectGenerator_GeneratedFile : TestProjectGeneratorBase_GeneratedFile
        {
            protected override IProjectGenerator CreateProjectReadyToGenerate()
            {
                return CreateVWGProjectReadyToGenerate();
            }

            protected override void AssertFileGeneratedCorrectly(IProjectGenerator projectGenerator, string fileContents)
            {
                VWGProjectGenerator vwgProjectGenerator = (VWGProjectGenerator)projectGenerator;
                AssertFileGeneratedCorrectlyVWG(vwgProjectGenerator, fileContents);
            }

            protected abstract void AssertFileGeneratedCorrectlyVWG(VWGProjectGenerator vwgProjectGenerator, string fileContents);
        }

        public class TestVWGProjectGenerator_GeneratedFile_UIManagerVWG : TestVWGProjectGenerator_GeneratedFile
        {
            protected override string GetFileName()
            {
                return "UIManagerVWG.cs";
            }

            protected override void AssertFileGeneratedCorrectlyVWG(VWGProjectGenerator vwgProjectGenerator, string fileContents)
            {
                ProjectFileManager projectFileManager = new ProjectFileManager(vwgProjectGenerator.ModelSolution.UIProjectName, OutputType.Library, CodeTemplateEnum.CSharpVisualStudio2005);
                TestVWGProjectTemplateLoader.AssertUiManagerVWGCorrect(fileContents, vwgProjectGenerator.ProjectName, projectFileManager.AssemblyName);
            }
        }

        public class TestVWGProjectGenerator_GeneratedFile_GlobalAsax : TestVWGProjectGenerator_GeneratedFile
        {
            protected override string GetFileName()
            {
                return "Global.asax";
            }

            protected override void AssertFileGeneratedCorrectlyVWG(VWGProjectGenerator vwgProjectGenerator, string fileContents)
            {
                TestVWGProjectTemplateLoader.AssertGlobal_asaxCorrect(fileContents, vwgProjectGenerator.ProjectName);
            }

            protected override bool CheckProjectHasFile(ProjectFileManager projectFileManager, string fileName)
            {
                return projectFileManager.HasContentFile(fileName);
            }
        }

        public class TestVWGProjectGenerator_GeneratedFile_GlobalAsaxCs : TestVWGProjectGenerator_GeneratedFile
        {
            protected override string GetFileName()
            {
                return "Global.asax.cs";
            }

            protected override void AssertFileGeneratedCorrectlyVWG(VWGProjectGenerator vwgProjectGenerator, string fileContents)
            {
                TestVWGProjectTemplateLoader.AssertGlobal_asax_csCorrect(fileContents, vwgProjectGenerator.ProjectName, vwgProjectGenerator.ProjectName, "v1.0");
            }
        }

        public class TestVWGProjectGenerator_GeneratedFile_MainForm : TestVWGProjectGenerator_GeneratedFile
        {
            protected override string GetFileName()
            {
                return "MainForm.cs";
            }

            protected override void AssertFileGeneratedCorrectlyVWG(VWGProjectGenerator vwgProjectGenerator, string fileContents)
            {
                TestVWGProjectTemplateLoader.AssertMainFormCorrect(fileContents, vwgProjectGenerator.ProjectName);
            }
        }

        public class TestVWGProjectGenerator_GeneratedFile_WebConfig : TestVWGProjectGenerator_GeneratedFile
        {
            protected override string GetFileName()
            {
                return "Web.config";
            }

            protected override bool CheckProjectHasFile(ProjectFileManager projectFileManager, string fileName)
            {
                return projectFileManager.HasFile(fileName);
            }

            protected override IProjectGenerator CreateProjectReadyToGenerate()
            {
                IProjectGenerator projectGenerator = base.CreateProjectReadyToGenerate();
                VWGProjectGenerator vwgProjectGenerator = (VWGProjectGenerator) projectGenerator;
                //DatabaseSettings databaseSettings = new DatabaseSettings();
                //vwgProjectGenerator.DatabaseSettings = databaseSettings;
                //databaseSettings.Vendor = GetRandomString();
                //databaseSettings.Server = GetRandomString();
                //databaseSettings.Port = GetRandomString();
                //databaseSettings.Database = GetRandomString();
                //databaseSettings.Username = GetRandomString();
                //databaseSettings.Password = GetRandomString();
                return vwgProjectGenerator;
            }

            protected override void AssertFileGeneratedCorrectlyVWG(VWGProjectGenerator vwgProjectGenerator, string fileContents)
            {
                //DatabaseSettings databaseSettings = vwgProjectGenerator.DatabaseSettings;
                //TestVWGProjectTemplateLoader.AssertWebConfigCorrect(fileContents, vwgProjectGenerator.ProjectName,
                //    databaseSettings.Vendor, databaseSettings.Server, databaseSettings.Port, 
                //    databaseSettings.Database, databaseSettings.Username, databaseSettings.Password);
                TestVWGProjectTemplateLoader.AssertWebConfigCorrect(fileContents,
                                                                    vwgProjectGenerator.SolutionGenerator.ModelSolution.
                                                                        ApplicationName,
                                                                    "InMemory", "", "", "", "", "");
            }
        }
    }
}